
#ifndef _UTILITY__PARALLELLY_EXECUTE_H__INCLUDED_
#define _UTILITY__PARALLELLY_EXECUTE_H__INCLUDED_

#include "Utility/ErrorCode.h"
#include "Utility/Mutex.h"
#include "Utility/Thread.h"
#include <deque>
#include <vector>

namespace nebula { namespace utility {

class ParallellyExecute
{
public:
	typedef void (*JobHandler)(void* job, void* param);

public:
	ParallellyExecute();
	~ParallellyExecute();

	NEBULA_ERROR_CODE Start(unsigned int thread_count, JobHandler, void* param);
	NEBULA_ERROR_CODE Join();
	NEBULA_ERROR_CODE Detach();

	NEBULA_ERROR_CODE AddJob(void* job);

private:
	enum State {
		S_INIT = 0,
		S_STARTED,
		S_STOPPING,
		S_STOPPED,
	};

	typedef std::deque<void*> JobQueue;
	typedef std::vector<Thread> JobThreads;

	struct Context
	{
	public:
		Context();

		NEBULA_ERROR_CODE start(unsigned thread_count, JobHandler, void* param);
		NEBULA_ERROR_CODE join();
		NEBULA_ERROR_CODE add_job(void* job);

	protected:
		void job_thread();

	private:
		State m_state;

		JobHandler m_job_handler;
		void* m_job_param;

		JobQueue m_job_queue;
		unsigned m_doing_count;
		Mutex m_queue_lock;

		JobThreads m_threads;
	};

	std::auto_ptr<Context> m_context;
	static void detached_join_thread(Context *);
};

}} // namespace nebula::utility

#endif // _UTILITY__PARALLELLY_EXECUTE_H__INCLUDED_

